1 /*
2 * Copyright (C) 2008 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.google.common.primitives;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkElementIndex;
21 import static com.google.common.base.Preconditions.checkNotNull;
22 import static com.google.common.base.Preconditions.checkPositionIndexes;
23 import static java.lang.Float.NEGATIVE_INFINITY;
24 import static java.lang.Float.POSITIVE_INFINITY;
25
26 import com.google.common.annotations.Beta;
27 import com.google.common.annotations.GwtCompatible;
28 import com.google.common.annotations.GwtIncompatible;
29 import com.google.common.base.Converter;
30
31 import java.io.Serializable;
32 import java.util.AbstractList;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.Comparator;
37 import java.util.List;
38 import java.util.RandomAccess;
39
40 import javax.annotation.Nullable;
41
42 /**
43 * Static utility methods pertaining to {@code float} primitives, that are not
44 * already found in either {@link Float} or {@link Arrays}.
45 *
46 * <p>See the Guava User Guide article on <a href=
47 * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
48 * primitive utilities</a>.
49 *
50 * @author Kevin Bourrillion
51 * @since 1.0
52 */
53 @GwtCompatible(emulated = true)
54 public final class Floats {
55 private Floats() {}
56
57 /**
58 * The number of bytes required to represent a primitive {@code float}
59 * value.
60 *
61 * @since 10.0
62 */
63 public static final int BYTES = Float.SIZE / Byte.SIZE;
64
65 /**
66 * Returns a hash code for {@code value}; equal to the result of invoking
67 * {@code ((Float) value).hashCode()}.
68 *
69 * @param value a primitive {@code float} value
70 * @return a hash code for the value
71 */
72 public static int hashCode(float value) {
73 // TODO(kevinb): is there a better way, that's still gwt-safe?
74 return ((Float) value).hashCode();
75 }
76
77 /**
78 * Compares the two specified {@code float} values using {@link
79 * Float#compare(float, float)}. You may prefer to invoke that method
80 * directly; this method exists only for consistency with the other utilities
81 * in this package.
82 *
83 * <p><b>Note:</b> this method simply delegates to the JDK method {@link
84 * Float#compare}. It is provided for consistency with the other primitive
85 * types, whose compare methods were not added to the JDK until JDK 7.
86 *
87 * @param a the first {@code float} to compare
88 * @param b the second {@code float} to compare
89 * @return the result of invoking {@link Float#compare(float, float)}
90 */
91 public static int compare(float a, float b) {
92 return Float.compare(a, b);
93 }
94
95 /**
96 * Returns {@code true} if {@code value} represents a real number. This is
97 * equivalent to, but not necessarily implemented as,
98 * {@code !(Float.isInfinite(value) || Float.isNaN(value))}.
99 *
100 * @since 10.0
101 */
102 public static boolean isFinite(float value) {
103 return NEGATIVE_INFINITY < value & value < POSITIVE_INFINITY;
104 }
105
106 /**
107 * Returns {@code true} if {@code target} is present as an element anywhere in
108 * {@code array}. Note that this always returns {@code false} when {@code
109 * target} is {@code NaN}.
110 *
111 * @param array an array of {@code float} values, possibly empty
112 * @param target a primitive {@code float} value
113 * @return {@code true} if {@code array[i] == target} for some value of {@code
114 * i}
115 */
116 public static boolean contains(float[] array, float target) {
117 for (float value : array) {
118 if (value == target) {
119 return true;
120 }
121 }
122 return false;
123 }
124
125 /**
126 * Returns the index of the first appearance of the value {@code target} in
127 * {@code array}. Note that this always returns {@code -1} when {@code target}
128 * is {@code NaN}.
129 *
130 * @param array an array of {@code float} values, possibly empty
131 * @param target a primitive {@code float} value
132 * @return the least index {@code i} for which {@code array[i] == target}, or
133 * {@code -1} if no such index exists.
134 */
135 public static int indexOf(float[] array, float target) {
136 return indexOf(array, target, 0, array.length);
137 }
138
139 // TODO(kevinb): consider making this public
140 private static int indexOf(
141 float[] array, float target, int start, int end) {
142 for (int i = start; i < end; i++) {
143 if (array[i] == target) {
144 return i;
145 }
146 }
147 return -1;
148 }
149
150 /**
151 * Returns the start position of the first occurrence of the specified {@code
152 * target} within {@code array}, or {@code -1} if there is no such occurrence.
153 *
154 * <p>More formally, returns the lowest index {@code i} such that {@code
155 * java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
156 * the same elements as {@code target}.
157 *
158 * <p>Note that this always returns {@code -1} when {@code target} contains
159 * {@code NaN}.
160 *
161 * @param array the array to search for the sequence {@code target}
162 * @param target the array to search for as a sub-sequence of {@code array}
163 */
164 public static int indexOf(float[] array, float[] target) {
165 checkNotNull(array, "array");
166 checkNotNull(target, "target");
167 if (target.length == 0) {
168 return 0;
169 }
170
171 outer:
172 for (int i = 0; i < array.length - target.length + 1; i++) {
173 for (int j = 0; j < target.length; j++) {
174 if (array[i + j] != target[j]) {
175 continue outer;
176 }
177 }
178 return i;
179 }
180 return -1;
181 }
182
183 /**
184 * Returns the index of the last appearance of the value {@code target} in
185 * {@code array}. Note that this always returns {@code -1} when {@code target}
186 * is {@code NaN}.
187 *
188 * @param array an array of {@code float} values, possibly empty
189 * @param target a primitive {@code float} value
190 * @return the greatest index {@code i} for which {@code array[i] == target},
191 * or {@code -1} if no such index exists.
192 */
193 public static int lastIndexOf(float[] array, float target) {
194 return lastIndexOf(array, target, 0, array.length);
195 }
196
197 // TODO(kevinb): consider making this public
198 private static int lastIndexOf(
199 float[] array, float target, int start, int end) {
200 for (int i = end - 1; i >= start; i--) {
201 if (array[i] == target) {
202 return i;
203 }
204 }
205 return -1;
206 }
207
208 /**
209 * Returns the least value present in {@code array}, using the same rules of
210 * comparison as {@link Math#min(float, float)}.
211 *
212 * @param array a <i>nonempty</i> array of {@code float} values
213 * @return the value present in {@code array} that is less than or equal to
214 * every other value in the array
215 * @throws IllegalArgumentException if {@code array} is empty
216 */
217 public static float min(float... array) {
218 checkArgument(array.length > 0);
219 float min = array[0];
220 for (int i = 1; i < array.length; i++) {
221 min = Math.min(min, array[i]);
222 }
223 return min;
224 }
225
226 /**
227 * Returns the greatest value present in {@code array}, using the same rules
228 * of comparison as {@link Math#min(float, float)}.
229 *
230 * @param array a <i>nonempty</i> array of {@code float} values
231 * @return the value present in {@code array} that is greater than or equal to
232 * every other value in the array
233 * @throws IllegalArgumentException if {@code array} is empty
234 */
235 public static float max(float... array) {
236 checkArgument(array.length > 0);
237 float max = array[0];
238 for (int i = 1; i < array.length; i++) {
239 max = Math.max(max, array[i]);
240 }
241 return max;
242 }
243
244 /**
245 * Returns the values from each provided array combined into a single array.
246 * For example, {@code concat(new float[] {a, b}, new float[] {}, new
247 * float[] {c}} returns the array {@code {a, b, c}}.
248 *
249 * @param arrays zero or more {@code float} arrays
250 * @return a single array containing all the values from the source arrays, in
251 * order
252 */
253 public static float[] concat(float[]... arrays) {
254 int length = 0;
255 for (float[] array : arrays) {
256 length += array.length;
257 }
258 float[] result = new float[length];
259 int pos = 0;
260 for (float[] array : arrays) {
261 System.arraycopy(array, 0, result, pos, array.length);
262 pos += array.length;
263 }
264 return result;
265 }
266
267 private static final class FloatConverter
268 extends Converter<String, Float> implements Serializable {
269 static final FloatConverter INSTANCE = new FloatConverter();
270
271 @Override
272 protected Float doForward(String value) {
273 return Float.valueOf(value);
274 }
275
276 @Override
277 protected String doBackward(Float value) {
278 return value.toString();
279 }
280
281 @Override
282 public String toString() {
283 return "Floats.stringConverter()";
284 }
285
286 private Object readResolve() {
287 return INSTANCE;
288 }
289 private static final long serialVersionUID = 1;
290 }
291
292 /**
293 * Returns a serializable converter object that converts between strings and
294 * floats using {@link Float#valueOf} and {@link Float#toString()}.
295 *
296 * @since 16.0
297 */
298 @Beta
299 public static Converter<String, Float> stringConverter() {
300 return FloatConverter.INSTANCE;
301 }
302
303 /**
304 * Returns an array containing the same values as {@code array}, but
305 * guaranteed to be of a specified minimum length. If {@code array} already
306 * has a length of at least {@code minLength}, it is returned directly.
307 * Otherwise, a new array of size {@code minLength + padding} is returned,
308 * containing the values of {@code array}, and zeroes in the remaining places.
309 *
310 * @param array the source array
311 * @param minLength the minimum length the returned array must guarantee
312 * @param padding an extra amount to "grow" the array by if growth is
313 * necessary
314 * @throws IllegalArgumentException if {@code minLength} or {@code padding} is
315 * negative
316 * @return an array containing the values of {@code array}, with guaranteed
317 * minimum length {@code minLength}
318 */
319 public static float[] ensureCapacity(
320 float[] array, int minLength, int padding) {
321 checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
322 checkArgument(padding >= 0, "Invalid padding: %s", padding);
323 return (array.length < minLength)
324 ? copyOf(array, minLength + padding)
325 : array;
326 }
327
328 // Arrays.copyOf() requires Java 6
329 private static float[] copyOf(float[] original, int length) {
330 float[] copy = new float[length];
331 System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
332 return copy;
333 }
334
335 /**
336 * Returns a string containing the supplied {@code float} values, converted
337 * to strings as specified by {@link Float#toString(float)}, and separated by
338 * {@code separator}. For example, {@code join("-", 1.0f, 2.0f, 3.0f)}
339 * returns the string {@code "1.0-2.0-3.0"}.
340 *
341 * <p>Note that {@link Float#toString(float)} formats {@code float}
342 * differently in GWT. In the previous example, it returns the string {@code
343 * "1-2-3"}.
344 *
345 * @param separator the text that should appear between consecutive values in
346 * the resulting string (but not at the start or end)
347 * @param array an array of {@code float} values, possibly empty
348 */
349 public static String join(String separator, float... array) {
350 checkNotNull(separator);
351 if (array.length == 0) {
352 return "";
353 }
354
355 // For pre-sizing a builder, just get the right order of magnitude
356 StringBuilder builder = new StringBuilder(array.length * 12);
357 builder.append(array[0]);
358 for (int i = 1; i < array.length; i++) {
359 builder.append(separator).append(array[i]);
360 }
361 return builder.toString();
362 }
363
364 /**
365 * Returns a comparator that compares two {@code float} arrays
366 * lexicographically. That is, it compares, using {@link
367 * #compare(float, float)}), the first pair of values that follow any
368 * common prefix, or when one array is a prefix of the other, treats the
369 * shorter array as the lesser. For example, {@code [] < [1.0f] < [1.0f, 2.0f]
370 * < [2.0f]}.
371 *
372 * <p>The returned comparator is inconsistent with {@link
373 * Object#equals(Object)} (since arrays support only identity equality), but
374 * it is consistent with {@link Arrays#equals(float[], float[])}.
375 *
376 * @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
377 * Lexicographical order article at Wikipedia</a>
378 * @since 2.0
379 */
380 public static Comparator<float[]> lexicographicalComparator() {
381 return LexicographicalComparator.INSTANCE;
382 }
383
384 private enum LexicographicalComparator implements Comparator<float[]> {
385 INSTANCE;
386
387 @Override
388 public int compare(float[] left, float[] right) {
389 int minLength = Math.min(left.length, right.length);
390 for (int i = 0; i < minLength; i++) {
391 int result = Float.compare(left[i], right[i]);
392 if (result != 0) {
393 return result;
394 }
395 }
396 return left.length - right.length;
397 }
398 }
399
400 /**
401 * Returns an array containing each value of {@code collection}, converted to
402 * a {@code float} value in the manner of {@link Number#floatValue}.
403 *
404 * <p>Elements are copied from the argument collection as if by {@code
405 * collection.toArray()}. Calling this method is as thread-safe as calling
406 * that method.
407 *
408 * @param collection a collection of {@code Number} instances
409 * @return an array containing the same values as {@code collection}, in the
410 * same order, converted to primitives
411 * @throws NullPointerException if {@code collection} or any of its elements
412 * is null
413 * @since 1.0 (parameter was {@code Collection<Float>} before 12.0)
414 */
415 public static float[] toArray(Collection<? extends Number> collection) {
416 if (collection instanceof FloatArrayAsList) {
417 return ((FloatArrayAsList) collection).toFloatArray();
418 }
419
420 Object[] boxedArray = collection.toArray();
421 int len = boxedArray.length;
422 float[] array = new float[len];
423 for (int i = 0; i < len; i++) {
424 // checkNotNull for GWT (do not optimize)
425 array[i] = ((Number) checkNotNull(boxedArray[i])).floatValue();
426 }
427 return array;
428 }
429
430 /**
431 * Returns a fixed-size list backed by the specified array, similar to {@link
432 * Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)},
433 * but any attempt to set a value to {@code null} will result in a {@link
434 * NullPointerException}.
435 *
436 * <p>The returned list maintains the values, but not the identities, of
437 * {@code Float} objects written to or read from it. For example, whether
438 * {@code list.get(0) == list.get(0)} is true for the returned list is
439 * unspecified.
440 *
441 * <p>The returned list may have unexpected behavior if it contains {@code
442 * NaN}, or if {@code NaN} is used as a parameter to any of its methods.
443 *
444 * @param backingArray the array to back the list
445 * @return a list view of the array
446 */
447 public static List<Float> asList(float... backingArray) {
448 if (backingArray.length == 0) {
449 return Collections.emptyList();
450 }
451 return new FloatArrayAsList(backingArray);
452 }
453
454 @GwtCompatible
455 private static class FloatArrayAsList extends AbstractList<Float>
456 implements RandomAccess, Serializable {
457 final float[] array;
458 final int start;
459 final int end;
460
461 FloatArrayAsList(float[] array) {
462 this(array, 0, array.length);
463 }
464
465 FloatArrayAsList(float[] array, int start, int end) {
466 this.array = array;
467 this.start = start;
468 this.end = end;
469 }
470
471 @Override public int size() {
472 return end - start;
473 }
474
475 @Override public boolean isEmpty() {
476 return false;
477 }
478
479 @Override public Float get(int index) {
480 checkElementIndex(index, size());
481 return array[start + index];
482 }
483
484 @Override public boolean contains(Object target) {
485 // Overridden to prevent a ton of boxing
486 return (target instanceof Float)
487 && Floats.indexOf(array, (Float) target, start, end) != -1;
488 }
489
490 @Override public int indexOf(Object target) {
491 // Overridden to prevent a ton of boxing
492 if (target instanceof Float) {
493 int i = Floats.indexOf(array, (Float) target, start, end);
494 if (i >= 0) {
495 return i - start;
496 }
497 }
498 return -1;
499 }
500
501 @Override public int lastIndexOf(Object target) {
502 // Overridden to prevent a ton of boxing
503 if (target instanceof Float) {
504 int i = Floats.lastIndexOf(array, (Float) target, start, end);
505 if (i >= 0) {
506 return i - start;
507 }
508 }
509 return -1;
510 }
511
512 @Override public Float set(int index, Float element) {
513 checkElementIndex(index, size());
514 float oldValue = array[start + index];
515 // checkNotNull for GWT (do not optimize)
516 array[start + index] = checkNotNull(element);
517 return oldValue;
518 }
519
520 @Override public List<Float> subList(int fromIndex, int toIndex) {
521 int size = size();
522 checkPositionIndexes(fromIndex, toIndex, size);
523 if (fromIndex == toIndex) {
524 return Collections.emptyList();
525 }
526 return new FloatArrayAsList(array, start + fromIndex, start + toIndex);
527 }
528
529 @Override public boolean equals(Object object) {
530 if (object == this) {
531 return true;
532 }
533 if (object instanceof FloatArrayAsList) {
534 FloatArrayAsList that = (FloatArrayAsList) object;
535 int size = size();
536 if (that.size() != size) {
537 return false;
538 }
539 for (int i = 0; i < size; i++) {
540 if (array[start + i] != that.array[that.start + i]) {
541 return false;
542 }
543 }
544 return true;
545 }
546 return super.equals(object);
547 }
548
549 @Override public int hashCode() {
550 int result = 1;
551 for (int i = start; i < end; i++) {
552 result = 31 * result + Floats.hashCode(array[i]);
553 }
554 return result;
555 }
556
557 @Override public String toString() {
558 StringBuilder builder = new StringBuilder(size() * 12);
559 builder.append('[').append(array[start]);
560 for (int i = start + 1; i < end; i++) {
561 builder.append(", ").append(array[i]);
562 }
563 return builder.append(']').toString();
564 }
565
566 float[] toFloatArray() {
567 // Arrays.copyOfRange() is not available under GWT
568 int size = size();
569 float[] result = new float[size];
570 System.arraycopy(array, start, result, 0, size);
571 return result;
572 }
573
574 private static final long serialVersionUID = 0;
575 }
576
577 /**
578 * Parses the specified string as a single-precision floating point value.
579 * The ASCII character {@code '-'} (<code>'\u002D'</code>) is recognized
580 * as the minus sign.
581 *
582 * <p>Unlike {@link Float#parseFloat(String)}, this method returns
583 * {@code null} instead of throwing an exception if parsing fails.
584 * Valid inputs are exactly those accepted by {@link Float#valueOf(String)},
585 * except that leading and trailing whitespace is not permitted.
586 *
587 * <p>This implementation is likely to be faster than {@code
588 * Float.parseFloat} if many failures are expected.
589 *
590 * @param string the string representation of a {@code float} value
591 * @return the floating point value represented by {@code string}, or
592 * {@code null} if {@code string} has a length of zero or cannot be
593 * parsed as a {@code float} value
594 * @since 14.0
595 */
596 @GwtIncompatible("regular expressions")
597 @Nullable
598 @Beta
599 public static Float tryParse(String string) {
600 if (Doubles.FLOATING_POINT_PATTERN.matcher(string).matches()) {
601 // TODO(user): could be potentially optimized, but only with
602 // extensive testing
603 try {
604 return Float.parseFloat(string);
605 } catch (NumberFormatException e) {
606 // Float.parseFloat has changed specs several times, so fall through
607 // gracefully
608 }
609 }
610 return null;
611 }
612 }